package shape;

import java.util.ArrayList;

import processing.core.PApplet;
import processing.core.PVector;

public class PolyhedraFace {

	ArrayList<PVector> vertex = new ArrayList<PVector>();
	int color;

	public PolyhedraFace() {
		this(10);
	}

	public PolyhedraFace(int color) {
		this.color = color;
	}

	public PolyhedraFace(ArrayList<PVector> vertex) {
		this.vertex = vertex;
	}

	public void addVertex(PVector v) {
		this.vertex.add(v);
	}

	public void draw(PApplet canvas) {
		if (!vertex.isEmpty() && vertex.size()>2) {
			canvas.pushStyle();
			canvas.noStroke();
			canvas.beginShape();
			canvas.fill(getColor());
			for (PVector v : vertex) {
				canvas.vertex(v.x, v.y, v.z);
			}
			PVector v0 = getVertex(0);
			canvas.vertex(v0.x, v0.y, v0.z);
			canvas.endShape();
//			//Draw normal
//			canvas.stroke(50);
//			PVector v1 = getVertex(1);
//			PVector v2 = getVertex(2);
//			PVector c = new PVector();
//			PVector.cross(PVector.sub(v1, v0), PVector.sub(v2, v0), c);
//			
//			PVector normal = PVector.add(v0,PVector.mult(c,0.5f));
//			canvas.line(v0.x, v0.y, v0.z, normal.x , normal.y, normal.z);
			canvas.popStyle();
		}
	}

	public void addVertex(float x, float y, float z) {
		this.vertex.add(new PVector(x, y, z));

	}

	public PVector getVertex(int i) {
		return vertex.get(i % vertex.size());
	}

	public PlaneEquation getPlaneEquation() {
		if (vertex.size() < 3)
			throw new RuntimeException(
					"A PolyhedraFace with less than three points cannot span a plane.");
		PVector v0 = getVertex(0);
		PVector v1 = getVertex(1);
		PVector v2 = getVertex(2);

		PVector c = new PVector();
		PVector.cross(PVector.sub(v1, v0), PVector.sub(v2, v0), c);

		return new PlaneEquation(c.x, c.y, c.z, -1 * PVector.dot(c, v0));
	}
	
	private static int getF(PlaneEquation eq,PVector vertex){
		return (eq.f(vertex)>0)?1:((eq.f(vertex)<0)?-1:0);
		
	}

	public ArrayList<PolyhedraFace> cutByPlane(PlaneEquation eq) {
		PolyhedraFace p1 = new PolyhedraFace(this.getColor());
		PolyhedraFace p2 = new PolyhedraFace(this.getColor());

		int i = 0;

		while (i < vertex.size() - 1
				&& getF(eq,getVertex(i)) == getF(eq,getVertex(i + 1))) {
			p1.addVertex(getVertex(i));
			i++;
		}
		p1.addVertex(getVertex(i));

		float t = -1.0f
				* eq.f(getVertex(i))
				/ (eq.f(PVector.sub(getVertex(i + 1), getVertex(i))) - eq
						.getD());
		System.out.println("FIrst intersect in t=" + t);
		if(t>1 || t<0 || Float.isNaN(t)) throw new RuntimeException("There was a problem cutting a polyhedron by a plane : T = " + t + "  -- w0=" + eq.f(getVertex(i)) + ", w1 = " + eq.f(getVertex(i+1)));
		PVector firstIntersect = PVector.add(getVertex(i),
				PVector.mult(PVector.sub(getVertex(i + 1), getVertex(i)), t));

		p1.addVertex(firstIntersect);
		p2.addVertex(firstIntersect);
		i++;

		while (i < vertex.size() - 1
				&& getF(eq,getVertex(i)) == getF(eq,getVertex(i + 1))) {
			p2.addVertex(getVertex(i));
			i++;
		}
		p2.addVertex(getVertex(i));

		t = -1.0f
				* eq.f(getVertex(i))
				/ (eq.f(PVector.sub(getVertex(i + 1), getVertex(i))) - eq
						.getD());
		System.out.println("Second intersect in t=" + t);
		if(t>1 || t<0 || Float.isNaN(t)) throw new RuntimeException("There was a problem cutting a polyhedron by a plane : T = " + t + "  -- w0=" + eq.f(getVertex(i)) + ", w1 = " + eq.f(getVertex(i+1)));
		PVector secondIntersect = PVector.add(getVertex(i),
				PVector.mult(PVector.sub(getVertex(i + 1), getVertex(i)), t));

		p2.addVertex(secondIntersect);
		p1.addVertex(secondIntersect);

		while (i < vertex.size()) {
			p1.addVertex(getVertex(i));
			i++;
		}

		ArrayList<PolyhedraFace> ret = new ArrayList<PolyhedraFace>(2);
		ret.add(0,p1);
		ret.add(1,p2);
		return ret;
	}

	public int getColor() {
		return color;
	}

	public int size() {
		return vertex.size();
	}
}
